define([],function(){
	var proxyBuilder = {
		filters:[],
		addFilter:function(advise){
			this.filters.push(advise);
		}
	};
	function around(name,obj, prop, advice){
		DEBUG("around:"+name+"_"+prop);
		 var exist = obj[prop];
		 var previous = function(){
		  return exist.apply(obj, arguments);
		 };
		 var advised = advice(previous,name,prop);
		 obj[prop] = function(){
		   //当调用remove后，advised为空
		    //利用闭包的作用域链中可以访问到advised跟previous变量，根据advised是否为空可以来决定调用谁
		  	return advised ? advised.apply(obj, arguments) : previous.apply(obj, arguments);
		 };
		 
		 return {
			  remove: function(){
			    //利用闭包的作用域链，在remove时将advised置空，这样执行过程中不会进入本次around
			   //这几个不能删
			   //obj[prop] = exist;
			   advised = null;
			   advice = null;
			   //previous = null;
			   //exist = null;
			   //obj = null;
			  }
		 }
	}
	proxyBuilder.packFilters = function(currentFilterObj){
		var name = currentFilterObj.scriptName;
		var methodName = currentFilterObj.methodName;
		var typeName = currentFilterObj.type;
		var $target = currentFilterObj.target;
		var $proxy = currentFilterObj.$proxy;
		var filters = this.filters;
		for(var i in filters){
			var nameReg = new RegExp(filters[i].matchName);
			var methodReg = new RegExp(filters[i].matchMethod);
			var typeReg = new RegExp(filters[i].matchType);

			if(nameReg.test(name) && methodReg.test(methodName) && typeReg.test(typeName)){
				var list = filters[i].list;
				for(var n in list){
					var  advice = list[n];
					around(name,$proxy, methodName, advice);
				}
				
			}
		}
	}
	proxyBuilder.addMethod = function(name,methodName,$proxy,target){
			$proxy[methodName] = function(){
				return target[methodName].apply(target,arguments);
			}
			var currentFilterObj = {
										$proxy:$proxy,
										target:target,
										methodName:methodName,
										scriptName:name,
										typeName : $proxy.typeName
									};
			this.packFilters(currentFilterObj);
	}
	proxyBuilder.createProxy = function (name,target,typeName){
		if(isFunction(target)){
			return target;
		}
		DEBUG("createProxy____:"+name);
		var $proxy = {};
		for(var mname in target){
			this.addMethod(name,mname,$proxy,target);
		}

		$proxy.scriptName =name;
		$proxy.target =target;
		$proxy.typeName=typeName;

		return $proxy;
	}
	
	
	return proxyBuilder;
});